/*
 * $Id$
 *
   Copyright 2005-2009 Chung, Hyung-Hwan.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an  BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

#include <xp/net/route.h>
#include <xp/net/inet.h>
#include <xp/bas/memory.h>
#include <xp/bas/locale.h>

#if defined(__linux)
#	include <net/route.h>
#	include <netinet/in.h>
#	include <sys/ioctl.h>
#endif

static inline int edit_ip4route (
	int s4, int cmd, const xp_char_t* iface, 
	const xp_ip4addr_t* ipaddr, int metric)
{
#if defined(__linux)
	struct rtentry rt;
	struct sockaddr_in* dst = (struct sockaddr_in*) &rt.rt_dst;
	struct sockaddr_in* msk = (struct sockaddr_in*) &rt.rt_genmask;
	int ret;

	xp_memset (&rt, 0, sizeof(rt));
	dst->sin_family = AF_INET;
	dst->sin_addr.s_addr = ipaddr->value;

	msk->sin_family = AF_INET;
	xp_inet4_strtoip (XP_T("255.255.255.255"), &msk->sin_addr.s_addr);

	rt.rt_flags |= RTF_UP | RTF_HOST;
#if defined(XP_CHAR_IS_MCHAR)
	rt.rt_dev = (char*)iface;
#else
	rt.rt_dev = xp_wcstomcs_dynamic (iface);
	if (rt.rt_dev == XP_NULL) return -1;
#endif

	/* +1 is needed according to the description in net/route.h */
	rt.rt_metric = metric + 1; 

	ret = ioctl (s4, cmd, &rt);
#if defined(XP_CHAR_IS_MCHAR)
	/* nothing to do */
#else
	xp_free (rt.rt_dev);	
#endif

	return ret;
#else
	/* not supported */
	return -1;
#endif
}

int xp_insertip4hostroute (
	int s4, const xp_char_t* iface, const xp_ip4addr_t* ipaddr, int metric)
{
	return edit_ip4route (s4, SIOCADDRT, iface, ipaddr, metric);
}

int xp_deleteip4hostroute (
	int s4, const xp_char_t* iface, const xp_ip4addr_t* ipaddr, int metric)
{
	return edit_ip4route (s4, SIOCDELRT, iface, ipaddr, metric);
}
